using System;
using System.Collections.Generic;

namespace Tools
{
    public class ReactiveProperty<T>
    {
        private static readonly IEqualityComparer<T> defaultEqualityComparer = ReactivePropertyEqualityComparer.GetDefault<T>();
        protected virtual IEqualityComparer<T> EqualityComparer => defaultEqualityComparer;

        protected T _value;

        private readonly Signal<T> _signal;

        public T Value
        {
            get => _value;
            set
            {
                if (!EqualityComparer.Equals(this._value, value))
                {
                    JustSetValue(value);
                    Dispatch(ref value);
                }
            }
        }

        public ReactiveProperty() : this(default(T))
        {
        }


        public ReactiveProperty(T initialValue)
        {
            _signal = new Signal<T>();
            JustSetValue(initialValue);
        }

        public void AddOnce(Action<T> callback)
        {
            _signal.AddOnce(callback);
        }

        public void AddListener(Action<T> callback, bool excuteImmediately = true)
        {
            _signal.AddListener(callback);
            if (excuteImmediately)
            {
                //添加监听的同时，立即执行自身的回调函数。
                callback?.Invoke(_value);
            }
        }

        public virtual void RemoveListener(Action<T> callback)
        {
            _signal.RemoveListener(callback);
        }

        public virtual void RemoveAllListeners()
        {
            _signal.RemoveAllListeners();
        }

        private void Dispatch(ref T value)
        {
            _signal.Dispatch(value);
        }

        public virtual void JustSetValue(T value)
        {
            _value = value;
        }

        public void SetValueAndForceDispath(T value)
        {
            JustSetValue(value);
            Dispatch(ref value);
        }

        public override string ToString()
        {
            return _value == null ? "" : _value.ToString();
        }
    }
}